home *** CD-ROM | disk | FTP | other *** search
- /* wmsetbg.c- sets root window background image and also works as
- * workspace background setting helper for wmaker
- *
- * WindowMaker window manager
- *
- * Copyright (c) 1998, 1999 Alfredo K. Kojima
- * Copyright (c) 1998 Dan Pascu
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
- * USA.
- */
-
- /*
- * TODO: rewrite, too dirty
- */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <X11/Xlib.h>
- #include <X11/Xutil.h>
- #include <X11/Xatom.h>
- #include <string.h>
- #include <pwd.h>
- #include <signal.h>
- #include <sys/types.h>
- #include <ctype.h>
-
- #include "../src/config.h"
-
- #ifdef HAVE_DLFCN_H
- #include <dlfcn.h>
- #endif
-
- #include "../src/wconfig.h"
-
- #include <WINGs.h>
- #include <wraster.h>
-
- #include <proplist.h>
-
- #define PROG_VERSION "wmsetbg (Window Maker) 2.6"
-
-
- #define WORKSPACE_COUNT (MAX_WORKSPACES+1)
-
-
- Display *dpy;
- char *display = "";
- Window root;
- int scr;
- int scrWidth;
- int scrHeight;
-
-
- Bool smooth = False;
-
-
- Pixmap CurrentPixmap = None;
- char *PixmapPath = NULL;
-
-
- extern Pixmap LoadJPEG(RContext *rc, char *file_name, int *width, int *height);
-
-
- typedef struct BackgroundTexture {
- int refcount;
-
- int solid;
-
- char *spec;
-
- XColor color;
- Pixmap pixmap; /* for all textures, including solid */
- int width; /* size of the pixmap */
- int height;
- } BackgroundTexture;
-
-
-
- RImage*
- loadImage(RContext *rc, char *file)
- {
- char *path;
- RImage *image;
-
- if (access(file, F_OK)!=0) {
- path = wfindfile(PixmapPath, file);
- if (!path) {
- wwarning("%s:could not find image file used in texture", file);
- return NULL;
- }
- } else {
- path = wstrdup(file);
- }
-
- image = RLoadImage(rc, path, 0);
- if (!image) {
- wwarning("%s:could not load image file used in texture:%s", path,
- RMessageForError(RErrorCode));
- }
- free(path);
-
- return image;
- }
-
-
- BackgroundTexture*
- parseTexture(RContext *rc, char *text)
- {
- BackgroundTexture *texture = NULL;
- proplist_t texarray;
- proplist_t val;
- int count;
- char *tmp;
- char *type;
-
- #define GETSTRORGOTO(val, str, i, label) \
- val = PLGetArrayElement(texarray, i);\
- if (!PLIsString(val)) {\
- wwarning("could not parse texture %s", text);\
- goto label;\
- }\
- str = PLGetString(val)
-
- texarray = PLGetProplistWithDescription(text);
- if (!texarray || !PLIsArray(texarray)
- || (count = PLGetNumberOfElements(texarray)) < 2) {
-
- wwarning("could not parse texture %s", text);
- if (texarray)
- PLRelease(texarray);
- return NULL;
- }
-
- texture = wmalloc(sizeof(BackgroundTexture));
- memset(texture, 0, sizeof(BackgroundTexture));
-
- GETSTRORGOTO(val, type, 0, error);
-
- if (strcasecmp(type, "solid")==0) {
- XColor color;
- Pixmap pixmap;
-
- texture->solid = 1;
-
- GETSTRORGOTO(val, tmp, 1, error);
-
- if (!XParseColor(dpy, DefaultColormap(dpy, scr), tmp, &color)) {
- wwarning("could not parse color %s in texture %s", tmp, text);
- goto error;
- }
- XAllocColor(dpy, DefaultColormap(dpy, scr), &color);
-
- pixmap = XCreatePixmap(dpy, root, 8, 8, DefaultDepth(dpy, scr));
- XSetForeground(dpy, DefaultGC(dpy, scr), color.pixel);
- XFillRectangle(dpy, pixmap, DefaultGC(dpy, scr), 0, 0, 8, 8);
-
- texture->pixmap = pixmap;
- texture->color = color;
- texture->width = 8;
- texture->height = 8;
- } else if (strcasecmp(type, "vgradient")==0
- || strcasecmp(type, "dgradient")==0
- || strcasecmp(type, "hgradient")==0) {
- XColor color;
- RColor color1, color2;
- RImage *image;
- Pixmap pixmap;
- int gtype;
- int iwidth, iheight;
-
- GETSTRORGOTO(val, tmp, 1, error);
-
- if (!XParseColor(dpy, DefaultColormap(dpy, scr), tmp, &color)) {
- wwarning("could not parse color %s in texture %s", tmp, text);
- goto error;
- }
-
- color1.red = color.red >> 8;
- color1.green = color.green >> 8;
- color1.blue = color.blue >> 8;
-
- GETSTRORGOTO(val, tmp, 2, error);
-
- if (!XParseColor(dpy, DefaultColormap(dpy, scr), tmp, &color)) {
- wwarning("could not parse color %s in texture %s", tmp, text);
- goto error;
- }
-
- color2.red = color.red >> 8;
- color2.green = color.green >> 8;
- color2.blue = color.blue >> 8;
-
- switch (type[0]) {
- case 'h':
- case 'H':
- gtype = RHorizontalGradient;
- iwidth = scrWidth;
- iheight = 8;
- break;
- case 'V':
- case 'v':
- gtype = RVerticalGradient;
- iwidth = 8;
- iheight = scrHeight;
- break;
- default:
- gtype = RDiagonalGradient;
- iwidth = scrWidth;
- iheight = scrHeight;
- break;
- }
-
- image = RRenderGradient(iwidth, iheight, &color1, &color2, gtype);
-
- if (!image) {
- wwarning("could not render gradient texture:%s",
- RMessageForError(RErrorCode));
- goto error;
- }
-
- if (!RConvertImage(rc, image, &pixmap)) {
- wwarning("could not convert texture:%s",
- RMessageForError(RErrorCode));
- RDestroyImage(image);
- goto error;
- }
-
- texture->width = image->width;
- texture->height = image->height;
- RDestroyImage(image);
-
- texture->pixmap = pixmap;
- } else if (strcasecmp(type, "mvgradient")==0
- || strcasecmp(type, "mdgradient")==0
- || strcasecmp(type, "mhgradient")==0) {
- XColor color;
- RColor **colors;
- RImage *image;
- Pixmap pixmap;
- int i, j;
- int gtype;
- int iwidth, iheight;
-
- colors = malloc(sizeof(RColor*)*(count-1));
- if (!colors) {
- wwarning("out of memory while parsing texture");
- goto error;
- }
- memset(colors, 0, sizeof(RColor*)*(count-1));
-
- for (i = 2; i < count; i++) {
- val = PLGetArrayElement(texarray, i);
- if (!PLIsString(val)) {
- wwarning("could not parse texture %s", text);
-
- for (j = 0; colors[j]!=NULL; j++)
- free(colors[j]);
- free(colors);
- goto error;
- }
- tmp = PLGetString(val);
-
- if (!XParseColor(dpy, DefaultColormap(dpy, scr), tmp, &color)) {
- wwarning("could not parse color %s in texture %s",
- tmp, text);
-
- for (j = 0; colors[j]!=NULL; j++)
- free(colors[j]);
- free(colors);
- goto error;
- }
- if (!(colors[i-2] = malloc(sizeof(RColor)))) {
- wwarning("out of memory while parsing texture");
-
- for (j = 0; colors[j]!=NULL; j++)
- free(colors[j]);
- free(colors);
- goto error;
- }
-
- colors[i-2]->red = color.red >> 8;
- colors[i-2]->green = color.green >> 8;
- colors[i-2]->blue = color.blue >> 8;
- }
-
- switch (type[1]) {
- case 'h':
- case 'H':
- gtype = RHorizontalGradient;
- iwidth = scrWidth;
- iheight = 8;
- break;
- case 'V':
- case 'v':
- gtype = RVerticalGradient;
- iwidth = 8;
- iheight = scrHeight;
- break;
- default:
- gtype = RDiagonalGradient;
- iwidth = scrWidth;
- iheight = scrHeight;
- break;
- }
-
- image = RRenderMultiGradient(iwidth, iheight, colors, gtype);
-
- for (j = 0; colors[j]!=NULL; j++)
- free(colors[j]);
- free(colors);
-
- if (!image) {
- wwarning("could not render gradient texture:%s",
- RMessageForError(RErrorCode));
- goto error;
- }
-
- if (!RConvertImage(rc, image, &pixmap)) {
- wwarning("could not convert texture:%s",
- RMessageForError(RErrorCode));
- RDestroyImage(image);
- goto error;
- }
-
- texture->width = image->width;
- texture->height = image->height;
- RDestroyImage(image);
-
- texture->pixmap = pixmap;
- } else if (strcasecmp(type, "cpixmap")==0
- || strcasecmp(type, "spixmap")==0
- || strcasecmp(type, "mpixmap")==0
- || strcasecmp(type, "tpixmap")==0) {
- XColor color;
- Pixmap pixmap = None;
- RImage *image = NULL;
- int w, h;
- int iwidth, iheight;
- RColor rcolor;
-
-
- GETSTRORGOTO(val, tmp, 1, error);
- /*
- if (toupper(type[0]) == 'T' || toupper(type[0]) == 'C')
- pixmap = LoadJPEG(rc, tmp, &iwidth, &iheight);
- */
-
- if (!pixmap) {
- image = loadImage(rc, tmp);
- if (!image) {
- goto error;
- }
- iwidth = image->width;
- iheight = image->height;
- }
-
- GETSTRORGOTO(val, tmp, 2, error);
-
- if (!XParseColor(dpy, DefaultColormap(dpy, scr), tmp, &color)) {
- wwarning("could not parse color %s in texture %s\n", tmp, text);
- RDestroyImage(image);
- goto error;
- }
- if (!XAllocColor(dpy, DefaultColormap(dpy, scr), &color)) {
- rcolor.red = color.red >> 8;
- rcolor.green = color.green >> 8;
- rcolor.blue = color.blue >> 8;
- RGetClosestXColor(rc, &rcolor, &color);
- } else {
- rcolor.red = 0;
- rcolor.green = 0;
- rcolor.blue = 0;
- }
- /* for images with a transparent color */
- if (image->data[3]) {
- RCombineImageWithColor(image, &rcolor);
- }
-
- switch (toupper(type[0])) {
- case 'T':
- texture->width = iwidth;
- texture->height = iheight;
- if (!pixmap && !RConvertImage(rc, image, &pixmap)) {
- wwarning("could not convert texture:%s",
- RMessageForError(RErrorCode));
- RDestroyImage(image);
- goto error;
- }
- if (image)
- RDestroyImage(image);
- break;
- case 'S':
- case 'M':
- if (toupper(type[0])=='S') {
- w = scrWidth;
- h = scrHeight;
- } else {
- if (iwidth*scrHeight > iheight*scrWidth) {
- w = scrWidth;
- h = (scrWidth*iheight)/iwidth;
- } else {
- h = scrHeight;
- w = (scrHeight*iwidth)/iheight;
- }
- }
- if (w != image->width || h != image->height) {
- RImage *simage;
-
- if (smooth)
- simage = RSmoothScaleImage(image, w, h);
- else
- simage = RScaleImage(image, w, h);
- if (!simage) {
- wwarning("could not scale image:%s",
- RMessageForError(RErrorCode));
- RDestroyImage(image);
- goto error;
- }
- RDestroyImage(image);
- image = simage;
- }
- iwidth = image->width;
- iheight = image->height;
-
- /* fall through */
- case 'C':
- {
- Pixmap cpixmap;
-
- if (!pixmap && !RConvertImage(rc, image, &pixmap)) {
- wwarning("could not convert texture:%s",
- RMessageForError(RErrorCode));
- RDestroyImage(image);
- goto error;
- }
-
- if (iwidth != scrWidth || iheight != scrHeight) {
- int x, y, sx, sy, w, h;
-
- cpixmap = XCreatePixmap(dpy, root, scrWidth, scrHeight,
- DefaultDepth(dpy, scr));
-
- XSetForeground(dpy, DefaultGC(dpy, scr), color.pixel);
- XFillRectangle(dpy, cpixmap, DefaultGC(dpy, scr),
- 0, 0, scrWidth, scrHeight);
-
- if (iheight < scrHeight) {
- h = iheight;
- y = (scrHeight - h)/2;
- sy = 0;
- } else {
- sy = (iheight - scrHeight)/2;
- y = 0;
- h = scrHeight;
- }
- if (iwidth < scrWidth) {
- w = iwidth;
- x = (scrWidth - w)/2;
- sx = 0;
- } else {
- sx = (iwidth - scrWidth)/2;
- x = 0;
- w = scrWidth;
- }
-
- XCopyArea(dpy, pixmap, cpixmap, DefaultGC(dpy, scr),
- sx, sy, w, h, x, y);
- XFreePixmap(dpy, pixmap);
- pixmap = cpixmap;
- }
- if (image)
- RDestroyImage(image);
-
- texture->width = scrWidth;
- texture->height = scrHeight;
- }
- break;
- }
-
- texture->pixmap = pixmap;
- texture->color = color;
- } else if (strcasecmp(type, "thgradient")==0
- || strcasecmp(type, "tvgradient")==0
- || strcasecmp(type, "tdgradient")==0) {
- XColor color;
- RColor color1, color2;
- RImage *image;
- RImage *gradient;
- RImage *tiled;
- Pixmap pixmap;
- int opaq;
- char *file;
- int gtype;
- int twidth, theight;
-
- GETSTRORGOTO(val, file, 1, error);
-
- GETSTRORGOTO(val, tmp, 2, error);
-
- opaq = atoi(tmp);
-
- GETSTRORGOTO(val, tmp, 3, error);
-
- if (!XParseColor(dpy, DefaultColormap(dpy, scr), tmp, &color)) {
- wwarning("could not parse color %s in texture %s", tmp, text);
- goto error;
- }
-
- color1.red = color.red >> 8;
- color1.green = color.green >> 8;
- color1.blue = color.blue >> 8;
-
- GETSTRORGOTO(val, tmp, 4, error);
-
- if (!XParseColor(dpy, DefaultColormap(dpy, scr), tmp, &color)) {
- wwarning("could not parse color %s in texture %s", tmp, text);
- goto error;
- }
-
- color2.red = color.red >> 8;
- color2.green = color.green >> 8;
- color2.blue = color.blue >> 8;
-
- image = loadImage(rc, file);
- if (!image) {
- goto error;
- }
-
- switch (type[1]) {
- case 'h':
- case 'H':
- gtype = RHorizontalGradient;
- twidth = scrWidth;
- theight = image->height > scrHeight ? scrHeight : image->height;
- break;
- case 'V':
- case 'v':
- gtype = RVerticalGradient;
- twidth = image->width > scrWidth ? scrWidth : image->width;
- theight = scrHeight;
- break;
- default:
- gtype = RDiagonalGradient;
- twidth = scrWidth;
- theight = scrHeight;
- break;
- }
- gradient = RRenderGradient(twidth, theight, &color1, &color2, gtype);
-
- if (!gradient) {
- wwarning("could not render texture:%s",
- RMessageForError(RErrorCode));
- RDestroyImage(gradient);
- RDestroyImage(image);
- goto error;
- }
-
- tiled = RMakeTiledImage(image, twidth, theight);
- if (!tiled) {
- wwarning("could not render texture:%s",
- RMessageForError(RErrorCode));
- RDestroyImage(gradient);
- RDestroyImage(image);
- goto error;
- }
- RDestroyImage(image);
-
- RCombineImagesWithOpaqueness(tiled, gradient, opaq);
- RDestroyImage(gradient);
-
- if (!RConvertImage(rc, tiled, &pixmap)) {
- wwarning("could not convert texture:%s",
- RMessageForError(RErrorCode));
- RDestroyImage(tiled);
- goto error;
- }
- texture->width = tiled->width;
- texture->height = tiled->height;
-
- RDestroyImage(tiled);
-
- texture->pixmap = pixmap;
- } else if (strcasecmp(type, "function")==0) {
- #ifdef HAVE_DLFCN_H
- void (*initFunc) (Display*, Colormap);
- RImage* (*mainFunc) (int, char**, int, int, int);
- Pixmap pixmap;
- RImage *image = 0;
- int success = 0;
- char *lib, *func, **argv = 0;
- void *handle = 0;
- int i, argc;
-
- if (count < 3)
- goto function_cleanup;
-
- /* get the library name */
- GETSTRORGOTO(val, lib, 1, function_cleanup);
-
- /* get the function name */
- GETSTRORGOTO(val, func, 2, function_cleanup);
-
- argc = count - 2;
- argv = (char**)wmalloc(argc * sizeof(char*));
-
- /* get the parameters */
- argv[0] = func;
- for (i=0; i<argc-1; i++) {
- GETSTRORGOTO(val, tmp, 3+i, function_cleanup);
- argv[i+1] = wstrdup(tmp);
- }
-
- handle = dlopen(lib, RTLD_LAZY);
- if (!handle) {
- wwarning("could not find library %s", lib);
- goto function_cleanup;
- }
-
- initFunc = dlsym(handle, "initWindowMaker");
- if (!initFunc) {
- wwarning("could not initialize library %s", lib);
- goto function_cleanup;
- }
- initFunc(dpy, DefaultColormap(dpy, scr));
-
- mainFunc = dlsym(handle, func);
- if (!mainFunc) {
- wwarning("could not find function %s::%s", lib, func);
- goto function_cleanup;
- }
- image = mainFunc(argc, argv, scrWidth, scrHeight, 0);
-
- if (!RConvertImage(rc, image, &pixmap)) {
- wwarning("could not convert texture:%s",
- RMessageForError(RErrorCode));
- goto function_cleanup;
- }
- texture->width = scrWidth;
- texture->height = scrHeight;
- texture->pixmap = pixmap;
- success = 1;
-
- function_cleanup:
- if (argv) {
- int i;
- for (i=0; i<argc; i++) {
- free(argv[i]);
- }
- }
- if (handle) {
- dlclose(handle);
- }
- if (image) {
- RDestroyImage(image);
- }
- if (!success) {
- goto error;
- }
- #else
- wwarning("function textures not supported");
- goto error;
- #endif
- } else {
- wwarning("invalid texture type %s", text);
- goto error;
- }
-
- texture->spec = wstrdup(text);
-
- return texture;
-
- error:
- if (texture)
- free(texture);
- if (texarray)
- PLRelease(texarray);
-
- return NULL;
- }
-
-
- void
- freeTexture(BackgroundTexture *texture)
- {
- if (texture->solid) {
- long pixel[1];
-
- pixel[0] = texture->color.pixel;
- /* dont free black/white pixels */
- if (pixel[0]!=BlackPixelOfScreen(DefaultScreenOfDisplay(dpy))
- && pixel[0]!=WhitePixelOfScreen(DefaultScreenOfDisplay(dpy)))
- XFreeColors(dpy, DefaultColormap(dpy, scr), pixel, 1, 0);
- }
- if (texture->pixmap) {
- XFreePixmap(dpy, texture->pixmap);
- }
- free(texture->spec);
- free(texture);
- }
-
-
- void
- setupTexture(RContext *rc, BackgroundTexture **textures, int *maxTextures,
- int workspace, char *texture)
- {
- BackgroundTexture *newTexture = NULL;
- int i;
-
- /* unset the texture */
- if (!texture) {
- if (textures[workspace]!=NULL) {
- textures[workspace]->refcount--;
-
- if (textures[workspace]->refcount == 0)
- freeTexture(textures[workspace]);
- }
- textures[workspace] = NULL;
- return;
- }
-
- if (textures[workspace]
- && strcasecmp(textures[workspace]->spec, texture)==0) {
- /* texture did not change */
- return;
- }
-
- /* check if the same texture is already created */
- for (i = 0; i < *maxTextures; i++) {
- if (textures[i] && strcasecmp(textures[i]->spec, texture)==0) {
- newTexture = textures[i];
- break;
- }
- }
-
- if (!newTexture) {
- /* create the texture */
- newTexture = parseTexture(rc, texture);
- }
- if (!newTexture)
- return;
-
- if (textures[workspace]!=NULL) {
-
- textures[workspace]->refcount--;
-
- if (textures[workspace]->refcount == 0)
- freeTexture(textures[workspace]);
- }
-
- newTexture->refcount++;
- textures[workspace] = newTexture;
-
- if (*maxTextures < workspace)
- *maxTextures = workspace;
- }
-
-
-
- Pixmap
- duplicatePixmap(Pixmap pixmap, int width, int height)
- {
- Display *tmpDpy;
- Pixmap copyP;
-
- /* must open a new display or the RetainPermanent will
- * leave stuff allocated in RContext unallocated after exit */
- tmpDpy = XOpenDisplay(display);
- if (!tmpDpy) {
- wwarning("could not open display to update background image information");
-
- return None;
- } else {
- XSync(dpy, False);
-
- copyP = XCreatePixmap(tmpDpy, root, width, height,
- DefaultDepth(tmpDpy, scr));
- XCopyArea(tmpDpy, pixmap, copyP, DefaultGC(tmpDpy, scr),
- 0, 0, width, height, 0, 0);
- XSync(tmpDpy, False);
-
- XSetCloseDownMode(tmpDpy, RetainPermanent);
- XCloseDisplay(tmpDpy);
- }
-
- return copyP;
- }
-
-
- static int
- dummyErrorHandler(Display *dpy, XErrorEvent *err)
- {
- return 0;
- }
-
- void
- setPixmapProperty(Pixmap pixmap)
- {
- static Atom prop = 0;
- Atom type;
- int format;
- unsigned long length, after;
- unsigned char *data;
- int mode;
-
- if (!prop) {
- prop = XInternAtom(dpy, "_XROOTPMAP_ID", False);
- }
-
- XGrabServer(dpy);
-
- /* Clear out the old pixmap */
- XGetWindowProperty(dpy, root, prop, 0L, 1L, False, AnyPropertyType,
- &type, &format, &length, &after, &data);
-
- if ((type == XA_PIXMAP) && (format == 32) && (length == 1)) {
- XSetErrorHandler(dummyErrorHandler);
- XKillClient(dpy, *((Pixmap *)data));
- XSync(dpy, False);
- XSetErrorHandler(NULL);
- mode = PropModeReplace;
- } else {
- mode = PropModeAppend;
- }
- if (pixmap)
- XChangeProperty(dpy, root, prop, XA_PIXMAP, 32, mode,
- (unsigned char *) &pixmap, 1);
- else
- XDeleteProperty(dpy, root, prop);
-
-
- XUngrabServer(dpy);
- XFlush(dpy);
- }
-
-
-
- void
- changeTexture(BackgroundTexture *texture)
- {
- if (!texture) {
- return;
- }
-
- if (texture->solid) {
- XSetWindowBackground(dpy, root, texture->color.pixel);
- } else {
- XSetWindowBackgroundPixmap(dpy, root, texture->pixmap);
- }
- XClearWindow(dpy, root);
-
- XSync(dpy, False);
-
- {
- Pixmap pixmap;
-
- pixmap = duplicatePixmap(texture->pixmap, texture->width,
- texture->height);
-
- setPixmapProperty(pixmap);
- }
- }
-
-
- int
- readmsg(int fd, unsigned char *buffer, int size)
- {
- int count;
-
- count = 0;
- while (size>0) {
- count = read(fd, buffer, size);
- if (count < 0)
- return -1;
- size -= count;
- buffer += count;
- *buffer = 0;
- }
-
- return size;
- }
-
-
- /*
- * Message Format:
- * sizeSntexture_spec - sets the texture for workspace n
- * sizeCn - change background texture to the one for workspace n
- * sizePpath - set the pixmap search path
- *
- * n is 4 bytes
- * size = 4 bytes for length of the message data
- */
- void
- helperLoop(RContext *rc)
- {
- BackgroundTexture *textures[WORKSPACE_COUNT];
- int maxTextures = 0;
- unsigned char buffer[2048], buf[8];
- int size;
- int errcount = 4;
-
- memset(textures, 0, WORKSPACE_COUNT*sizeof(BackgroundTexture*));
-
-
- while (1) {
- int workspace;
-
- /* get length of message */
- if (readmsg(0, buffer, 4) < 0) {
- wsyserror("error reading message from Window Maker");
- errcount--;
- if (errcount == 0) {
- wfatal("quitting");
- exit(1);
- }
- continue;
- }
- memcpy(buf, buffer, 4);
- buf[4] = 0;
- size = atoi(buf);
-
- /* get message */
- if (readmsg(0, buffer, size) < 0) {
- wsyserror("error reading message from Window Maker");
- errcount--;
- if (errcount == 0) {
- wfatal("quitting");
- exit(1);
- }
- continue;
- }
- #ifdef DEBUG
- printf("RECEIVED %s\n",buffer);
- #endif
- if (buffer[0]!='P' && buffer[0]!='K') {
- memcpy(buf, &buffer[1], 4);
- buf[4] = 0;
- workspace = atoi(buf);
- if (workspace < 0 || workspace >= WORKSPACE_COUNT) {
- wwarning("received message with invalid workspace number %i\n",
- workspace);
- continue;
- }
- }
-
- switch (buffer[0]) {
- case 'S':
- #ifdef DEBUG
- printf("set texture %s\n", &buffer[5]);
- #endif
- setupTexture(rc, textures, &maxTextures, workspace, &buffer[5]);
- break;
-
- case 'C':
- #ifdef DEBUG
- printf("change texture %i\n", workspace);
- #endif
- if (!textures[workspace]) {
- changeTexture(textures[0]);
- } else {
- changeTexture(textures[workspace]);
- }
- break;
-
- case 'P':
- #ifdef DEBUG
- printf("change pixmappath %s\n", &buffer[1]);
- #endif
- if (PixmapPath)
- free(PixmapPath);
- PixmapPath = wstrdup(&buffer[1]);
- break;
-
- case 'U':
- #ifdef DEBUG
- printf("unset workspace %i\n", workspace);
- #endif
- setupTexture(rc, textures, &maxTextures, workspace, NULL);
- break;
-
- case 'K':
- #ifdef DEBUG
- printf("exit command\n");
- #endif
- exit(0);
-
- default:
- wwarning("unknown message received");
- break;
- }
- }
- }
-
-
- void
- updateDomain(char *domain, char *key, char *texture)
- {
- char *program = "wdwrite";
-
- system(wstrappend("wdwrite ",
- wstrappend(domain, smooth ? " SmoothWorkspaceBack YES"
- : " SmoothWorkspaceBack NO")));
-
- execlp(program, program, domain, key, texture, NULL);
- wwarning("warning could not run \"%s\"", program);
- }
-
-
-
- char*
- globalDefaultsPathForDomain(char *domain)
- {
- char path[1024];
-
- sprintf(path, "%s/WindowMaker/%s", SYSCONFDIR, domain);
-
- return wstrdup(path);
- }
-
-
- proplist_t
- getValueForKey(char *domain, char *keyName)
- {
- char *path;
- proplist_t key;
- proplist_t d;
- proplist_t val;
-
- key = PLMakeString(keyName);
-
- /* try to find PixmapPath in user defaults */
- path = wdefaultspathfordomain(domain);
- d = PLGetProplistWithPath(path);
- if (!d) {
- wwarning("could not open domain file %s", path);
- }
- free(path);
-
- if (d && !PLIsDictionary(d)) {
- PLRelease(d);
- d = NULL;
- }
- if (d) {
- val = PLGetDictionaryEntry(d, key);
- } else {
- val = NULL;
- }
- /* try to find PixmapPath in global defaults */
- if (!val) {
- path = globalDefaultsPathForDomain(domain);
- if (!path) {
- wwarning("could not locate file for domain %s", domain);
- d = NULL;
- } else {
- d = PLGetProplistWithPath(path);
- free(path);
- }
-
- if (d && !PLIsDictionary(d)) {
- PLRelease(d);
- d = NULL;
- }
- if (d) {
- val = PLGetDictionaryEntry(d, key);
-
- } else {
- val = NULL;
- }
- }
-
- if (val)
- PLRetain(val);
-
- PLRelease(key);
- if (d)
- PLRelease(d);
-
- return val;
- }
-
-
-
- char*
- getPixmapPath(char *domain)
- {
- proplist_t val;
- char *ptr, *data;
- int len, i, count;
-
- val = getValueForKey(domain, "PixmapPath");
-
- if (!val || !PLIsArray(val)) {
- if (val)
- PLRelease(val);
- return wstrdup("");
- }
-
- count = PLGetNumberOfElements(val);
- len = 0;
- for (i=0; i<count; i++) {
- proplist_t v;
-
- v = PLGetArrayElement(val, i);
- if (!v || !PLIsString(v)) {
- continue;
- }
- len += strlen(PLGetString(v))+1;
- }
-
- ptr = data = wmalloc(len+1);
- *ptr = 0;
-
- for (i=0; i<count; i++) {
- proplist_t v;
-
- v = PLGetArrayElement(val, i);
- if (!v || !PLIsString(v)) {
- continue;
- }
- strcpy(ptr, PLGetString(v));
-
- ptr += strlen(PLGetString(v));
- *ptr = ':';
- ptr++;
- }
- if (i>0)
- ptr--; *(ptr--) = 0;
-
- PLRelease(val);
-
- return data;
- }
-
-
- char*
- getFullPixmapPath(char *file)
- {
- char *tmp;
-
- if (!PixmapPath || !(tmp = wfindfile(PixmapPath, file))) {
- int bsize = 512;
- char *path = wmalloc(bsize);
-
- while (!getcwd(path, bsize)) {
- free(path);
- bsize += bsize/2;
- path = malloc(bsize);
- }
-
- tmp = wstrappend(path, "/");
- free(path);
- path = wstrappend(tmp, file);
- free(tmp);
-
- return path;
- }
-
- /* the file is in the PixmapPath */
- free(tmp);
-
- return wstrdup(file);
- }
-
-
-
- void
- wAbort()
- {
- wfatal("aborting");
- exit(1);
- }
-
-
-
- void
- print_help(char *ProgName)
- {
- printf("Usage: %s [options] [image]\n", ProgName);
- puts("Sets the workspace background to the specified image or a texture and optionally update Window Maker configuration");
- puts("");
- #define P(m) puts(m)
- P(" -display display to use");
- P(" -d, --dither dither image");
- P(" -m, --match match colors");
- P(" -S, --smooth smooth scaled image");
- P(" -b, --back-color <color> background color");
- P(" -t, --tile tile image");
- P(" -e, --center center image");
- P(" -s, --scale scale image (default)");
- P(" -a, --maxscale scale image and keep aspect ratio");
- P(" -u, --update-wmaker update WindowMaker domain database");
- P(" -D, --update-domain <domain> update <domain> database");
- P(" -c, --colors <cpc> colors per channel to use");
- P(" -p, --parse <texture> proplist style texture specification");
- P(" -w, --workspace <workspace> update background for the specified workspace");
- P(" --version show version of wmsetbg and exit");
- P(" --help show this help and exit");
- #undef P
- }
-
-
-
- void
- changeTextureForWorkspace(char *domain, char *texture, int workspace)
- {
- proplist_t array;
- proplist_t val;
- char *value;
- int j;
-
- val = PLGetProplistWithDescription(texture);
- if (!val) {
- wwarning("could not parse texture %s", texture);
- return;
- }
-
- array = getValueForKey("WindowMaker", "WorkspaceSpecificBack");
-
- if (!array) {
- array = PLMakeArrayFromElements(NULL, NULL);
- }
-
- j = PLGetNumberOfElements(array);
- if (workspace >= j) {
- proplist_t empty;
-
- empty = PLMakeArrayFromElements(NULL, NULL);
-
- while (j++ < workspace-1) {
- PLAppendArrayElement(array, empty);
- }
- PLAppendArrayElement(array, val);
- } else {
- PLRemoveArrayElement(array, workspace);
- PLInsertArrayElement(array, val, workspace);
- }
-
- value = PLGetDescription(array);
- updateDomain(domain, "WorkspaceSpecificBack", value);
- }
-
-
- int
- main(int argc, char **argv)
- {
- int i;
- int helperMode = 0;
- RContext *rc;
- RContextAttributes rattr;
- char *style = "spixmap";
- char *back_color = "gray20";
- char *image_name = NULL;
- char *domain = "WindowMaker";
- int update=0, cpc=4, render_mode=RDitheredRendering, obey_user=0;
- char *texture = NULL;
- int workspace = -1;
-
- signal(SIGINT, SIG_DFL);
- signal(SIGTERM, SIG_DFL);
- signal(SIGQUIT, SIG_DFL);
- signal(SIGSEGV, SIG_DFL);
- signal(SIGBUS, SIG_DFL);
- signal(SIGFPE, SIG_DFL);
- signal(SIGABRT, SIG_DFL);
- signal(SIGHUP, SIG_DFL);
- signal(SIGPIPE, SIG_DFL);
- signal(SIGCHLD, SIG_DFL);
-
- WMInitializeApplication("wmsetbg", &argc, argv);
-
- for (i=1; i<argc; i++) {
- if (strcmp(argv[i], "-helper")==0) {
- helperMode = 1;
- } else if (strcmp(argv[i], "-display")==0) {
- i++;
- if (i>=argc) {
- wfatal("too few arguments for %s\n", argv[i-1]);
- exit(1);
- }
- display = argv[i];
- } else if (strcmp(argv[i], "-s")==0
- || strcmp(argv[i], "--scale")==0) {
- style = "spixmap";
- } else if (strcmp(argv[i], "-t")==0
- || strcmp(argv[i], "--tile")==0) {
- style = "tpixmap";
- } else if (strcmp(argv[i], "-e")==0
- || strcmp(argv[i], "--center")==0) {
- style = "cpixmap";
- } else if (strcmp(argv[i], "-a")==0
- || strcmp(argv[i], "--maxscale")==0) {
- style = "mpixmap";
- } else if (strcmp(argv[i], "-d")==0
- || strcmp(argv[i], "--dither")==0) {
- render_mode = RDitheredRendering;
- obey_user++;
- } else if (strcmp(argv[i], "-m")==0
- || strcmp(argv[i], "--match")==0) {
- render_mode = RBestMatchRendering;
- obey_user++;
- } else if (strcmp(argv[i], "-S")==0
- || strcmp(argv[i], "--smooth")==0) {
- smooth = True;
- } else if (strcmp(argv[i], "-u")==0
- || strcmp(argv[i], "--update-wmaker")==0) {
- update++;
- } else if (strcmp(argv[i], "-D")==0
- || strcmp(argv[i], "--update-domain")==0) {
- update++;
- i++;
- if (i>=argc) {
- wfatal("too few arguments for %s\n", argv[i-1]);
- exit(1);
- }
- domain = wstrdup(argv[i]);
- } else if (strcmp(argv[i], "-c")==0
- || strcmp(argv[i], "--colors")==0) {
- i++;
- if (i>=argc) {
- wfatal("too few arguments for %s\n", argv[i-1]);
- exit(1);
- }
- if (sscanf(argv[i], "%i", &cpc)!=1) {
- wfatal("bad value for colors per channel: \"%s\"\n", argv[i]);
- exit(1);
- }
- } else if (strcmp(argv[i], "-b")==0
- || strcmp(argv[i], "--back-color")==0) {
- i++;
- if (i>=argc) {
- wfatal("too few arguments for %s\n", argv[i-1]);
- exit(1);
- }
- back_color = argv[i];
- } else if (strcmp(argv[i], "-p")==0
- || strcmp(argv[i], "--parse")==0) {
- i++;
- if (i>=argc) {
- wfatal("too few arguments for %s\n", argv[i-1]);
- exit(1);
- }
- texture = argv[i];
- } else if (strcmp(argv[i], "-w")==0
- || strcmp(argv[i], "--workspace")==0) {
- i++;
- if (i>=argc) {
- wfatal("too few arguments for %s\n", argv[i-1]);
- exit(1);
- }
- if (sscanf(argv[i], "%i", &workspace)!=1) {
- wfatal("bad value for workspace number: \"%s\"",
- argv[i]);
- exit(1);
- }
- } else if (strcmp(argv[i], "--version")==0) {
-
- printf(PROG_VERSION);
- exit(0);
-
- } else if (strcmp(argv[i], "--help")==0) {
- print_help(argv[0]);
- exit(0);
- } else if (argv[i][0] != '-') {
- image_name = argv[i];
- } else {
- printf("%s: invalid argument '%s'\n", argv[0], argv[i]);
- printf("Try '%s --help' for more information\n", argv[0]);
- exit(1);
- }
- }
- if (!image_name && !texture && !helperMode) {
- printf("%s: you must specify a image file name or a texture\n",
- argv[0]);
- printf("Try '%s --help' for more information\n", argv[0]);
- exit(1);
- }
-
-
- PixmapPath = getPixmapPath(domain);
- if (!smooth) {
- proplist_t val;
- #if 0 /* some problem with Alpha... TODO: check if its right */
- val = PLGetDictionaryEntry(domain,
- PLMakeString("SmoothWorkspaceBack"));
- #else
- val = getValueForKey(domain, "SmoothWorkspaceBack");
- #endif
-
- if (val && PLIsString(val) && strcasecmp(PLGetString(val), "YES")==0)
- smooth = True;
- }
-
- dpy = XOpenDisplay(display);
- if (!dpy) {
- wfatal("could not open display");
- exit(1);
- }
- #if 0
- XSynchronize(dpy, 1);
- #endif
-
- root = DefaultRootWindow(dpy);
-
- scr = DefaultScreen(dpy);
-
- scrWidth = WidthOfScreen(DefaultScreenOfDisplay(dpy));
- scrHeight = HeightOfScreen(DefaultScreenOfDisplay(dpy));
-
- if (!obey_user && DefaultDepth(dpy, scr) <= 8)
- render_mode = RDitheredRendering;
-
- rattr.flags = RC_RenderMode | RC_ColorsPerChannel
- | RC_StandardColormap;
- rattr.render_mode = render_mode;
- rattr.colors_per_channel = cpc;
- rattr.standard_colormap_mode = RCreateStdColormap;
-
- rc = RCreateContext(dpy, scr, &rattr);
- if (!rc) {
- wfatal("could not initialize wrlib:",
- RMessageForError(RErrorCode));
- exit(1);
- }
-
- if (helperMode) {
- /* lower priority, so that it wont use all the CPU */
- nice(1000);
-
- helperLoop(rc);
- } else {
- BackgroundTexture *tex;
- char buffer[4098];
-
- if (!texture) {
- char *image_path = getFullPixmapPath(image_name);
-
- sprintf(buffer, "(%s, \"%s\", %s)", style, image_path, back_color);
- free(image_path);
- texture = (char*)buffer;
- }
-
- if (update && workspace < 0) {
- updateDomain(domain, "WorkspaceBack", texture);
- }
-
- tex = parseTexture(rc, texture);
- if (!tex)
- exit(1);
-
- if (workspace<0)
- changeTexture(tex);
- else {
- /* always update domain */
- changeTextureForWorkspace(domain, texture, workspace);
- }
- }
-
- return 0;
- }
-
-